/*<copyright>
Mo+ Solution Builder is a model oriented programming language and IDE, used for building models and generating code and other documents in a model driven development process.

Copyright (C) 2013 Dave Clemmer, Intelligent Coding Solutions, LLC

This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.

This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more details.

You should have received a copy of the GNU General Public License along with this program.  If not, see <http://www.gnu.org/licenses/>.
</copyright>*/
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows.Input;
using System.ComponentModel;
using MoPlus.Data;
using MoPlus.Interpreter;
using MoPlus.Interpreter.BLL.Config;
using MoPlus.Interpreter.BLL.Diagrams;
using MoPlus.Interpreter.BLL.Entities;
using MoPlus.Interpreter.BLL.Interpreter;
using MoPlus.Interpreter.BLL.Models;
using MoPlus.Interpreter.BLL.Solutions;
using MoPlus.Interpreter.BLL.Specifications;
using MoPlus.Interpreter.BLL.Workflows;
using MoPlus.ViewModel.Messaging;
using MoPlus.ViewModel.Resources;
using MoPlus.ViewModel.Events;
using MoPlus.ViewModel.Events.Diagrams;
using MoPlus.ViewModel.Diagrams;
using MoPlus.ViewModel.Events.Entities;
using MoPlus.ViewModel.Entities;
using MoPlus.ViewModel.Events.Interpreter;
using MoPlus.ViewModel.Interpreter;
using MoPlus.ViewModel.Events.Models;
using MoPlus.ViewModel.Models;
using MoPlus.ViewModel.Events.Solutions;
using MoPlus.ViewModel.Solutions;
using MoPlus.ViewModel.Events.Workflows;
using MoPlus.ViewModel.Workflows;

namespace MoPlus.ViewModel.Models
{
	///--------------------------------------------------------------------------------
	/// <summary>This class provides views for collections of
	/// ModelProperty instances.</summary>
	///
	/// This file is code generated and should not be modified by hand.
	/// If you need to customize this file outside of protected areas,
	/// change the Status value below to something other than
	/// Generated to prevent changes from being overwritten.
	///
	/// <CreatedByUserName>INCODE-1\Dave</CreatedByUserName>
	/// <CreatedDate>8/12/2013</CreatedDate>
	/// <Status>Generated</Status>
	///--------------------------------------------------------------------------------
	public partial class ModelPropertiesViewModel : EditWorkspaceViewModel
	{
		#region "Menus"
		///--------------------------------------------------------------------------------
		/// <summary>This property gets MenuLabelNewModelProperty.</summary>
		///--------------------------------------------------------------------------------
		public string MenuLabelNewModelProperty
		{
			get
			{
				return DisplayValues.ContextMenu_NewModelProperty;
			}
		}

		///--------------------------------------------------------------------------------
		/// <summary>This property gets MenuLabelNewModelPropertyToolTip.</summary>
		///--------------------------------------------------------------------------------
		public string MenuLabelNewModelPropertyToolTip
		{
			get
			{
				return DisplayValues.ContextMenu_NewModelPropertyToolTip;
			}
		}

		///--------------------------------------------------------------------------------
		/// <summary>This property gets MenuLabelDelete.</summary>
		///--------------------------------------------------------------------------------
		public string MenuLabelDelete
		{
			get
			{
				return DisplayValues.ContextMenu_Delete;
			}
		}

		///--------------------------------------------------------------------------------
		/// <summary>This property gets MenuLabelDeleteToolTip.</summary>
		///--------------------------------------------------------------------------------
		public string MenuLabelDeleteToolTip
		{
			get
			{
				return DisplayValues.ContextMenu_DeleteToolTip;
			}
		}

		#endregion "Menus"

		#region "Editing Support"
		///--------------------------------------------------------------------------------
		/// <summary>This property gets IsEdited.</summary>
		///--------------------------------------------------------------------------------
		public override bool IsEdited
		{
			get
			{
				if (ItemsToAdd.Count > 0)
				{
					return true;
				}
				if (ItemsToDelete.Count > 0)
				{
					return true;
				}
				foreach (IEditWorkspaceViewModel item in Items)
				{
					if (item.IsEdited == true)
					{
						return true;
					}
				}
				return false;
			}
		}

		#endregion "Editing Support"

		#region "Command Processing"
		///--------------------------------------------------------------------------------
		/// <summary>This method resets the data.</summary>
		///--------------------------------------------------------------------------------
		protected override void OnReset()
		{
			ResetItems();
		}

		///--------------------------------------------------------------------------------
		/// <summary>This method resets the data.</summary>
		///--------------------------------------------------------------------------------
		public override void Reset()
		{
			OnReset();
		}

		///--------------------------------------------------------------------------------
		/// <summary>This method sets the default values.</summary>
		///--------------------------------------------------------------------------------
		protected override void OnSetDefaults()
		{
			foreach (ModelPropertyViewModel item in Items.OfType<ModelPropertyViewModel>())
			{
				item.Defaults();
			}
		}

		///--------------------------------------------------------------------------------
		/// <summary>This method sets the default values.</summary>
		///--------------------------------------------------------------------------------
		public void Defaults()
		{
			OnSetDefaults();
		}

		///--------------------------------------------------------------------------------
		/// <summary>This method updates the view model data and sends update command back
		/// to the solution builder.</summary>
		///--------------------------------------------------------------------------------
		protected override void OnUpdate()
		{
			// send update for any updated children
			foreach (ModelPropertyViewModel item in ModelProperties)
			{
				if (item.IsEdited == true)
				{
					item.Update();
				}
			}
			// send update for any new children
			foreach (ModelPropertyViewModel item in ItemsToAdd.OfType<ModelPropertyViewModel>())
			{
				item.Update();
				ModelProperties.Add(item);
			}
			ItemsToAdd.Clear();

			// send delete for any deleted children
			foreach (ModelPropertyViewModel item in ItemsToDelete.OfType<ModelPropertyViewModel>())
			{
				item.Delete();
				ModelProperties.Remove(item);
			}
			ItemsToDelete.Clear();

			// reset modified for children
			foreach (ModelPropertyViewModel item in ModelProperties)
			{
				item.ResetModified(false);
			}
		}

		///--------------------------------------------------------------------------------
		/// <summary>This method updates the view model data and sends update command back
		/// to the solution builder.</summary>
		///--------------------------------------------------------------------------------
		public void Update()
		{
			OnUpdate();
		}

		///--------------------------------------------------------------------------------
		/// <summary>This method processes the new modelproperty command.</summary>
		///--------------------------------------------------------------------------------
		public void ProcessNewModelPropertyCommand()
		{
			ModelPropertyEventArgs message = new ModelPropertyEventArgs();
			message.ModelProperty = new ModelProperty();
			message.ModelProperty.ModelPropertyID = Guid.NewGuid();
			message.ModelProperty.ModelObjectID = ModelObject.ModelObjectID;
			message.ModelProperty.ModelObject = ModelObject;
			message.ModelObjectID = ModelObject.ModelObjectID;
			message.ModelProperty.Solution = Solution;
			message.Solution = Solution;
			if (message.ModelProperty.ModelObject != null)
			{
				message.ModelProperty.Order = message.ModelProperty.ModelObject.ModelPropertyList.Count + 1;
			}
			message.WorkspaceID = WorkspaceID;
			Mediator.NotifyColleagues<ModelPropertyEventArgs>(MediatorMessages.Command_EditModelPropertyRequested, message);
		}

		///--------------------------------------------------------------------------------
		/// <summary>This method applies modelproperty updates.</summary>
		///--------------------------------------------------------------------------------
		public void ProcessEditModelPropertyPerformed(ModelPropertyEventArgs data)
		{
			try
			{
				bool isItemMatch = false;
				if (data != null && data.ModelProperty != null)
				{
					foreach (ModelPropertyViewModel item in ModelProperties)
					{
						if (item.ModelProperty.ModelPropertyID == data.ModelProperty.ModelPropertyID)
						{
							isItemMatch = true;
							item.ModelProperty.TransformDataFromObject(data.ModelProperty, null, false);
							item.OnUpdated(item, null);
							item.ShowInTreeView();
							break;
						}
					}
					if (isItemMatch == false)
					{
						// add new ModelProperty
						data.ModelProperty.ModelObject = ModelObject;
						ModelPropertyViewModel newItem = new ModelPropertyViewModel(data.ModelProperty, Solution);
						newItem.Updated += new EventHandler(Children_Updated);
						ModelProperties.Add(newItem);
						ModelObject.ModelPropertyList.Add(newItem.ModelProperty);
						Solution.ModelPropertyList.Add(newItem.ModelProperty);
						Items.Add(newItem);
						OnUpdated(this, null);
						newItem.ShowInTreeView();
					}
				}
			}
			catch (Exception ex)
			{
				ShowIssue(ex.Message + ex.StackTrace);
			}
		}

		///--------------------------------------------------------------------------------
		/// <summary>This method applies modelproperty deletes.</summary>
		///--------------------------------------------------------------------------------
		public void ProcessDeleteModelPropertyPerformed(ModelPropertyEventArgs data)
		{
			try
			{
				bool isItemMatch = false;
				if (data != null && data.ModelProperty != null)
				{
					foreach (ModelPropertyViewModel item in ModelProperties.ToList<ModelPropertyViewModel>())
					{
						if (item.ModelProperty.ModelPropertyID == data.ModelProperty.ModelPropertyID)
						{
							// remove item from tabs, if present
							WorkspaceEventArgs message = new WorkspaceEventArgs();
							message.ItemID = item.ModelProperty.ModelPropertyID;
							Mediator.NotifyColleagues<WorkspaceEventArgs>(MediatorMessages.Command_CloseItemRequested, message);
	
							// delete children
							for (int i = item.Items.Count - 1; i >= 0; i--)
							{
							}
	
							// delete item
							isItemMatch = true;
							ModelProperties.Remove(item);
							ModelObject.ModelPropertyList.Remove(item.ModelProperty);
							Items.Remove(item);
							ModelObject.ResetModified(true);
							OnUpdated(this, null);
							break;
						}
					}
					if (isItemMatch == false)
					{
						ShowIssue(DisplayValues.Issue_DeleteItemNotFound);
					}
				}
			}
			catch (Exception ex)
			{
				ShowIssue(ex.Message + ex.StackTrace);
			}
		}

		#endregion "Command Processing"

		#region "Properties"

		///--------------------------------------------------------------------------------
		/// <summary>This property gets or sets ModelProperty lists.</summary>
		///--------------------------------------------------------------------------------
		public EnterpriseDataObjectList<ModelPropertyViewModel> ModelProperties { get; set; }

		///--------------------------------------------------------------------------------
		/// <summary>This property gets or sets ModelObject.</summary>
		///--------------------------------------------------------------------------------
		public ModelObject ModelObject { get; set; }

		#endregion "Properties"

		#region "Methods"
		///--------------------------------------------------------------------------------
		/// <summary>This method loads ModelProperties into the view model.</summary>
		///
		/// <param name="modelObject">The modelObject to load.</param>
		/// <param name="solution">The associated solution.</param>
		/// <param name="loadChildren">Flag indicating whether to perform a deeper load.</param>
		///--------------------------------------------------------------------------------
		public void LoadModelProperties(ModelObject modelObject, Solution solution, bool loadChildren = true)
		{
			// attach the items
			Items.Clear();
			if (ModelProperties == null)
			{
				ModelProperties = new EnterpriseDataObjectList<ModelPropertyViewModel>();
			}
			if (loadChildren == true)
			{
				foreach (ModelProperty item in modelObject.ModelPropertyList)
				{
					ModelPropertyViewModel itemView = new ModelPropertyViewModel(item, solution);
					itemView.Updated += new EventHandler(Children_Updated);
					ModelProperties.Add(itemView);
					Items.Add(itemView);
				}
			}
		}

		///--------------------------------------------------------------------------------
		/// <summary>This method refreshes the view model.</summary>
		/// 
		/// <param name="refreshChildren">Flag indicating whether children should be refreshed.</param>
		///--------------------------------------------------------------------------------
		public void Refresh(bool refreshChildren, int refreshLevel = 0)
		{
			HasErrors = !IsValid;
			HasCustomizations = false;
			if (refreshChildren == true || refreshLevel > 0)
			{
				foreach (ModelPropertyViewModel item in ModelProperties)
				{
					item.Refresh(refreshChildren, refreshLevel-1);
				}
			}
			foreach (ModelPropertyViewModel item in ModelProperties)
			{
				if (item.HasCustomizations == true)
				{
					HasCustomizations = true;
				}
				if (item.HasErrors == true)
				{
					HasErrors = true;
				}
			}
			Items.Sort("ItemOrder", SortDirection.Ascending);
			OnPropertyChanged("Items");
			OnPropertyChanged("HasCustomizations");
			OnPropertyChanged("HasErrors");
		}

		///--------------------------------------------------------------------------------
		/// <summary>This method disposes of resources in the view model.</summary>
		///--------------------------------------------------------------------------------
		protected override void OnDispose()
		{
			if (ModelProperties != null)
			{
				foreach (ModelPropertyViewModel itemView in ModelProperties)
				{
					itemView.Updated -= Children_Updated;
					itemView.Dispose();
				}
				ModelProperties.Clear();
				ModelProperties = null;
			}
			ModelObject = null;
			base.OnDispose();
		}

		///--------------------------------------------------------------------------------
		/// <summary>This method manages the update of this view when children are updated.</summary>
		/// 
		/// <param name="sender">The sender of the updated event.</param>
		/// <param name="e">The event arguments.</param>
		///--------------------------------------------------------------------------------
		private void Children_Updated(object sender, EventArgs e)
		{
			Refresh(false, 1);
			OnUpdated(this, e);
		}
		
		///--------------------------------------------------------------------------------
		/// <summary>This method returns the parent view model corresponding to
		/// the input message.</summary>
		///
		/// <param name="data">The message data to find parent for.</param>
		///--------------------------------------------------------------------------------
		public EditWorkspaceViewModel FindParentViewModel(SolutionModelEventArgs data)
		{
			if (data is ModelPropertyEventArgs && (data as ModelPropertyEventArgs).ModelObjectID == ModelObject.ModelObjectID)
			{
				return this;
			}
			
			return null;
		}

		///--------------------------------------------------------------------------------
		/// <summary>This method is used to copy/paste a new item.</summary>
		///
		/// <param name="copyItem">The item to copy/paste.</param>
		/// <param name="savePaste">Flag to determine whether to save the results of the paste.</param>
		///--------------------------------------------------------------------------------
		public ModelPropertyViewModel PasteModelProperty(ModelPropertyViewModel copyItem, bool savePaste = true)
		{
			ModelProperty newItem = new ModelProperty();
			newItem.ReverseInstance = new ModelProperty();
			newItem.TransformDataFromObject(copyItem.ModelProperty, null, false);
			newItem.ModelPropertyID = Guid.NewGuid();
			newItem.IsAutoUpdated = false;
			
			// try to find referenced Enumeration by existing id first, second by old id, finally by name
			newItem.DefinedByEnumeration = Solution.EnumerationList.FindByID((Guid)copyItem.ModelProperty.DefinedByEnumerationID);
			if (newItem.DefinedByEnumeration == null && Solution.PasteNewGuids[copyItem.ModelProperty.DefinedByEnumerationID.ToString()] is Guid)
			{
				newItem.DefinedByEnumeration = Solution.EnumerationList.FindByID((Guid)Solution.PasteNewGuids[copyItem.ModelProperty.DefinedByEnumerationID.ToString()]);
			}
			if (newItem.DefinedByEnumeration == null)
			{
				newItem.DefinedByEnumeration = Solution.EnumerationList.Find("Name", copyItem.ModelProperty.Name);
			}
			if (newItem.DefinedByEnumeration == null)
			{
				newItem.OldDefinedByEnumerationID = newItem.DefinedByEnumerationID;
				newItem.DefinedByEnumerationID = Guid.Empty;
			}
			// try to find referenced Value by existing id first, second by old id, finally by name
			newItem.DefinedByValue = Solution.ValueList.FindByID((Guid)copyItem.ModelProperty.DefinedByValueID);
			if (newItem.DefinedByValue == null && Solution.PasteNewGuids[copyItem.ModelProperty.DefinedByValueID.ToString()] is Guid)
			{
				newItem.DefinedByValue = Solution.ValueList.FindByID((Guid)Solution.PasteNewGuids[copyItem.ModelProperty.DefinedByValueID.ToString()]);
			}
			if (newItem.DefinedByValue == null)
			{
				newItem.DefinedByValue = Solution.ValueList.Find("Name", copyItem.ModelProperty.Name);
			}
			if (newItem.DefinedByValue == null)
			{
				newItem.OldDefinedByValueID = newItem.DefinedByValueID;
				newItem.DefinedByValueID = Guid.Empty;
			}
			newItem.ModelObject = ModelObject;
			newItem.Solution = Solution;
			ModelPropertyViewModel newView = new ModelPropertyViewModel(newItem, Solution);
			newView.ResetModified(true);
			AddModelProperty(newView);

			// paste children
			if (savePaste == true)
			{
				Solution.ModelPropertyList.Add(newItem);
				ModelObject.ModelPropertyList.Add(newItem);
				newView.OnUpdated(this, null);
				Solution.ResetModified(true);
			}
			return newView;
		}

		///--------------------------------------------------------------------------------
		/// <summary>This method adds an instance of ModelProperty to the view model.</summary>
		/// 
		/// <param name="itemView">The ModelProperty to add.</param>
		///--------------------------------------------------------------------------------
		public void AddModelProperty(ModelPropertyViewModel itemView)
		{
			itemView.Updated += new EventHandler(Children_Updated);
			ModelProperties.Add(itemView);
			Add(itemView);
		}

		///--------------------------------------------------------------------------------
		/// <summary>This method deletes an instance of ModelProperty from the view model.</summary>
		/// 
		/// <param name="itemView">The ModelProperty to delete.</param>
		///--------------------------------------------------------------------------------
		public void DeleteModelProperty(ModelPropertyViewModel itemView)
		{
			itemView.Updated -= Children_Updated;
			ModelProperties.Remove(itemView);
			Delete(itemView);
		}

		#endregion "Methods"

		#region "Constructors"

		///--------------------------------------------------------------------------------
		/// <summary>The default constructor (for reflection, etc.).</summary>
		///--------------------------------------------------------------------------------
		public ModelPropertiesViewModel()
		{
			Name = Resources.DisplayValues.NodeName_ModelProperties;
		}

		///--------------------------------------------------------------------------------
		/// <summary>Create the instance with the designer view and other data.</summary>
		///
		/// <param name="modelObject">The modelObject to load.</param>
		/// <param name="solution">The associated solution.</param>
		/// <param name="loadChildren">Flag indicating whether to perform a deeper load.</param>
		///--------------------------------------------------------------------------------
		public ModelPropertiesViewModel(ModelObject modelObject, Solution solution, bool loadChildren = true)
		{
			Name = Resources.DisplayValues.NodeName_ModelProperties;
			Solution = solution;
			ModelObject = modelObject;
			LoadModelProperties(modelObject, solution, loadChildren);
		}

		#endregion "Constructors"
	}
}
